﻿using System;

namespace Dapper.Sharding.Maui
{
    internal class CsharpTypeToDbType
    {

        public static string Create(DataBaseType dbType, DataBaseVersion dbVersion, Type type, double length = 0, string columnType = null, int scale = 0)
        {
            if (!string.IsNullOrEmpty(columnType))
            {
                if (columnType == "jsons")
                {
                    if (dbType == DataBaseType.MySql)
                    {
                        return "longtext";
                    }
                    if (dbType == DataBaseType.Postgresql)
                    {
                        return "text";
                    }
                    if (dbType == DataBaseType.Sqlite)
                    {
                        return "text";
                    }
                    if (dbType == DataBaseType.ClickHouse)
                    {
                        return "String";
                    }
                    if (dbType == DataBaseType.Oracle)
                    {
                        return "NCLOB";
                    }
                    if (dbType == DataBaseType.SqlServer)
                    {
                        return "nvarchar(max)";
                    }
                }

                if (dbType != DataBaseType.Postgresql)
                {
                    if (columnType == "json" || columnType == "jsonb")
                    {
                        if (dbType == DataBaseType.MySql)
                        {
                            return "json";
                        }
                        else if (dbType == DataBaseType.SqlServer)
                        {
                            return "nvarchar(max)";
                        }
                        else if (dbType == DataBaseType.ClickHouse)
                        {
                            return "String";
                        }
                        else if (dbType == DataBaseType.Oracle)
                        {
                            return "NCLOB";
                        }
                        else
                        {
                            return "text";
                        }
                    }
                }

                if (dbType != DataBaseType.MySql)
                {
                    if (columnType == "longtext")
                    {
                        if (dbType == DataBaseType.SqlServer)
                        {
                            return "nvarchar(max)";
                        }
                        else if (dbType == DataBaseType.Oracle)
                        {
                            return "NCLOB";
                        }
                        else if (dbType == DataBaseType.ClickHouse)
                        {
                            return "String";
                        }
                        else
                        {
                            return "text";
                        }
                    }
                }
                return columnType;
            }
            return CreateSqliteType(type);
        }

        private static string UnknownTypeMessage(string t)
        {
            return $"unknown type {t}, please set ColumnAttribute ColumnType like [Column(columnType:\"jsonb\")] or other database type.";
        }

        private static string CreateSqliteType(Type type)
        {
            if (type == typeof(Guid) || type == typeof(Guid?))
            {
                return "TEXT COLLATE NOCASE";
            }

            if (type == typeof(string))
            {
                return "TEXT COLLATE NOCASE";
            }

            if (type == typeof(bool) || type == typeof(bool?))
            {
                return "NUMERIC";
            }

            if (type == typeof(byte) || type == typeof(sbyte) || type == typeof(byte?) || type == typeof(sbyte?))
            {
                return "NUMERIC";
            }

            if (type == typeof(short) || type == typeof(ushort) || type == typeof(short?) || type == typeof(ushort?))
            {
                return "NUMERIC";
            }

            if (type == typeof(int) || type.BaseType == typeof(Enum) || type == typeof(uint) || type == typeof(int?) || type == typeof(uint?))
            {
                return "NUMERIC";
            }

            if (type == typeof(long) || type == typeof(ulong) || type == typeof(long?) || type == typeof(ulong?))
            {
                return "NUMERIC";
            }

            if (type == typeof(float) || type == typeof(float?))
            {
                return "NUMERIC";
            }

            if (type == typeof(double) || type == typeof(double?))
            {
                return "NUMERIC";
            }

            if (type == typeof(decimal) || type == typeof(decimal?))
            {
                return "NUMERIC";
            }

            if (type == typeof(DateTime) || type == typeof(DateTimeOffset) || type == typeof(DateTime?) || type == typeof(DateTimeOffset?))
            {
                return "DATETIME";
            }

#if CORE6
            if (type == typeof(DateOnly) || type == typeof(DateOnly?))
            {
                if (ShardingFactory.DateOnlyFormat == DbTypeDateOnly.Date)
                {
                    return "DATE";
                }
                else if (ShardingFactory.DateOnlyFormat == DbTypeDateOnly.DateTime)
                {
                    return "DATETIME";
                }
                else if (ShardingFactory.DateOnlyFormat == DbTypeDateOnly.Number)
                {
                    return "NUMERIC";
                }
                else if (ShardingFactory.DateOnlyFormat == DbTypeDateOnly.String)
                {
                    return "TEXT";
                }
                return "NUMERIC";
            }

            if (type == typeof(TimeOnly) || type == typeof(TimeOnly?))
            {
                if (ShardingFactory.TimeOnlyFormat == DbTypeTimeOnly.TimeSpan)
                {
                    return "DATETIME";
                }
                else if (ShardingFactory.TimeOnlyFormat == DbTypeTimeOnly.Time)
                {
                    return "TIME";
                }
                else if (ShardingFactory.TimeOnlyFormat == DbTypeTimeOnly.DateTime)
                {
                    return "DATETIME";
                }
                else if (ShardingFactory.TimeOnlyFormat == DbTypeTimeOnly.Number)
                {
                    return "NUMERIC";
                }
                else if (ShardingFactory.TimeOnlyFormat == DbTypeTimeOnly.String)
                {
                    return "TEXT";
                }
                return "NUMERIC";
            }
#endif

            throw new Exception(UnknownTypeMessage(type.Name));

            //return "BLOB";
        }

    }
}
